package com.wiscamp.ninechapters.problems.infrastructure.repositories;

import com.wiscamp.ninechapters.common.core.CollectionHelper;
import com.wiscamp.ninechapters.common.core.CustomBeanUtils;
import com.wiscamp.ninechapters.problems.domain.gateway.TagGateway;
import com.wiscamp.ninechapters.problems.domain.models.problems.answers.*;
import com.wiscamp.ninechapters.problems.domain.models.problems.problems.*;
import com.wiscamp.ninechapters.problems.domain.models.problems.problems.composite.*;
import com.wiscamp.ninechapters.problems.domain.models.problems.problems.simple.*;
import com.wiscamp.ninechapters.problems.domain.models.problems.questions.*;
import com.wiscamp.ninechapters.problems.domain.models.types.ProblemType;
import com.wiscamp.ninechapters.problems.domain.models.types.QuestionType;
import com.wiscamp.ninechapters.problems.domain.repositories.ExamRepository;
import com.wiscamp.ninechapters.problems.domain.repositories.ProblemCollectionRepository;
import com.wiscamp.ninechapters.problems.domain.repositories.ProblemTypeRepository;
import com.wiscamp.ninechapters.problems.domain.repositories.QuestionTypeRepository;
import com.wiscamp.ninechapters.problems.enums.AnswerTypes;
import com.wiscamp.ninechapters.problems.enums.ProblemModes;
import com.wiscamp.ninechapters.problems.enums.QuestionModes;
import com.wiscamp.ninechapters.problems.infrastructure.converters.ProblemConverter;
import com.wiscamp.ninechapters.problems.infrastructure.po.problems.*;
import com.wiscamp.ninechapters.tags.domain.models.TagName;
import cube.common.core.CollectionUtils;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

/**
 * 题创建器 （负责题实体的创建）
 */
@Component
public class ProblemBuilder {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final ProblemAccessor problemAccessor;

    private final ProblemTypeRepository problemTypeRepository;

    private final QuestionTypeRepository questionTypeRepository;

    private final ProblemCollectionRepository problemCollectionRepository;

    private final ExamRepository examRepository;

    private final TagGateway tagGateway;

    public ProblemBuilder(ProblemAccessor problemAccessor, ProblemTypeRepository problemTypeRepository, QuestionTypeRepository questionTypeRepository, ProblemCollectionRepository problemCollectionRepository, ExamRepository examRepository, TagGateway tagGateway) {
        this.problemAccessor = problemAccessor;
        this.problemTypeRepository = problemTypeRepository;
        this.questionTypeRepository = questionTypeRepository;
        this.problemCollectionRepository = problemCollectionRepository;
        this.examRepository = examRepository;
        this.tagGateway = tagGateway;
    }


    // region converter
    public Problem toProblem(@NotNull ProblemPO problemPO) {
        Problem problem = null;
        var problemType = problemTypeRepository.getProblemType(problemPO.getProblemTypeId());
        if (Objects.isNull(problemType)) {
            logger.error("未发现此题关联的题类型。");
            return null;
        }

        ProblemModes problemMode = problemType.getProblemMode();
        // 对于简单题及单一问题类型复合题来说，第一个问题的questionType及questionMode就是整道题的类型
        // 获取题中第一个问题的questionType及questionMode
        var questionPO = problemAccessor.getFirstQuestion(problemPO.getProblemId());
        long questionTypeId = questionPO.getQuestionTypeId();
        QuestionType questionType = questionTypeRepository.getQuestionType(questionTypeId);
        QuestionModes questionMode = questionType.getQuestionMode();

        switch (problemMode) {
            case SIMPLE -> problem = buildSimpleProblem(problemPO, questionMode, questionPO);
            case COMPOSITE -> problem = buildCompositeProblem(problemPO, questionMode);
            case HYBRID -> problem = buildHybridProblem(problemPO);
            default -> logger.error("无效的题模式。");
        }

        if (Objects.isNull(problem)) {
            logger.error("从题PO构建题Problem失败。题编号: {}", problemPO.getProblemId());
            return null;
        }

        problem.setProblemType(problemType);
        problem.setProblemTypeName(problemType.getTypeName());

        // Set the points and tags
        var primaryPoints = tagGateway.getPrimaryKnowledgePointsByProblem(problemPO.getProblemId(), true);
        var minorPoints = tagGateway.getPrimaryKnowledgePointsByProblem(problemPO.getProblemId(), false);
        problem.setPrimaryKnowledgePoints(primaryPoints);
        problem.setMinorKnowledgePoints(minorPoints);
        //problem.setTagNames(problemPO.getTagNames());
        return problem;
    }


    public Problem toProblem(@NotNull ProblemView problemView) {
        Problem problem = null;

        var problemPO = problemAccessor.getProblemPO(problemView.getProblemId());

        var problemType = problemTypeRepository.getProblemType(problemView.getProblemTypeId());
        if (Objects.isNull(problemType)) {
            logger.error("未发现此题关联的题类型。");
            return null;
        }

        ProblemModes problemMode = problemType.getProblemMode();
        // 对于简单题及单一问题类型复合题来说，第一个问题的questionType及questionMode就是整道题的类型
        // 获取题中第一个问题的questionType及questionMode
        var questionPO = problemAccessor.getFirstQuestion(problemView.getProblemId());
        long questionTypeId = questionPO.getQuestionTypeId();
        QuestionType questionType = questionTypeRepository.getQuestionType(questionTypeId);
        QuestionModes questionMode = questionType.getQuestionMode();

        switch (problemMode) {
            case SIMPLE -> problem = buildSimpleProblem(problemPO, questionMode, questionPO);
            case COMPOSITE -> problem = buildCompositeProblem(problemPO, questionMode);
            case HYBRID -> problem = buildHybridProblem(problemPO);
            default -> logger.error("无效的题模式。");
        }

        if (Objects.isNull(problem)) {
            logger.error("从题PO构建题Problem失败。题编号: {}", problemView.getProblemId());
            return null;
        }

        problem.setProblemType(problemType);
        problem.setProblemTypeName(problemType.getTypeName());
        problem.setProblemIndex(problemView.getProblemIndex());
        problem.setCollectionName(problemView.getCollectionName());
        problem.setCollectionId(problemView.getCollectionId());

        // Set the points and tags
        var primaryPoints = tagGateway.getPrimaryKnowledgePointsByProblem(problemView.getProblemId(), true);
        var minorPoints = tagGateway.getPrimaryKnowledgePointsByProblem(problemView.getProblemId(), false);
        problem.setPrimaryKnowledgePoints(primaryPoints);
        problem.setMinorKnowledgePoints(minorPoints);
        //problem.setTagNames(problemView.);

        var tagNames = tagGateway.getTagNamesByProblem(problemView.getProblemId());
        problem.setTagNames(tagNames);

        var commonQuestionMode = problemType.getCommonQuestionMode();
        problem.setQuestionModeName(commonQuestionMode.getName());

        problem.setCreatorName(problemView.getCreatorName());
        problem.setModifierName(problemView.getModifierName());
        problem.setProblemTypeName(problemView.getProblemTypeName());
        problem.setCollectionName(problemView.getCollectionName());
        return problem;
    }

    public Stem toStem(@NotNull StemPO stemPO) {
        return ProblemConverter.Instance.toStem(stemPO);
    }

    public Question toQuestion(@NotNull QuestionPO questionPO) {
        long problemTypeId = questionPO.getProblemTypeId();
        ProblemType problemType = problemTypeRepository.getProblemType(problemTypeId);
        if (Objects.isNull(problemType)) {
            logger.error("获取问题关联的题类型失败。问题编号: {}, 题类型编号: {}", questionPO.getQuestionId(), questionPO.getProblemTypeId());
        }

        long questionTypeId = questionPO.getQuestionTypeId();
        QuestionType questionType = questionTypeRepository.getQuestionType(questionTypeId);
        if (Objects.isNull(questionType)) {
            logger.warn("无效的问题类型。问题类型编号: {}", questionTypeId);
            return null;
        }

        QuestionModes questionMode = questionType.getQuestionMode();
        if (Objects.isNull(questionMode)) {
            logger.error("未找到匹配的问题模式。问题编号: {}", questionPO.getQuestionId());
            return null;
        }
        Question question = ProblemConverter.Instance.toQuestion(questionPO);
        question.setHasOptions(questionType.isHasOption());
        var answerPOs = questionPO.getAnswers();
        var firstAnswerPO = problemAccessor.getFirstAnswerPO(answerPOs);
        var optionPOs = questionPO.getOptions();
        var solutionPOs = questionPO.getSolutions();

        Collection<Answer> answers = new ArrayList<>();
        if (!answerPOs.isEmpty())
            answers = CollectionHelper.convertToArrayList(answerPOs, this::toAnswer);

        Collection<Solution> solutions = new ArrayList<>();
        if (!solutionPOs.isEmpty()) {
            solutions = CollectionHelper.convertToArrayList(solutionPOs, this::toSolution);
        }

        Collection<Option> options = new ArrayList<>();
        if (!optionPOs.isEmpty()) {
            options = CollectionHelper.convertToArrayList(optionPOs, this::toOption);
        }

        switch (questionMode) {
            // 10 判断问题
            case TRUE_FALSE -> {
                var question10 = new TrueFalseQuestion();
                CustomBeanUtils.copyProperties(question, question10);
                question10.setAnswer((BooleanAnswer) toAnswer(firstAnswerPO));
                question = question10;
            }
            // 20 单选问题
            case MULTIPLE_CHOICE_TWO_OPTIONS, MULTIPLE_CHOICE_THREE_OPTIONS, MULTIPLE_CHOICE_FOUR_OPTIONS, MULTIPLE_CHOICE_FIVE_OPTIONS -> {
                var question20 = new MultipleChoiceQuestion();
                CustomBeanUtils.copyProperties(question, question20);
                question20.setOptions(options);
                question20.setAnswer((OptionAnswer) toAnswer(firstAnswerPO));
                question = question20;
            }
            // 30 多选问题
            case MULTIPLE_SELECTION_FOUR_OPTIONS, MULTIPLE_SELECTION_FIVE_OPTIONS, MULTIPLE_SELECTION_SIX_OPTIONS, MULTIPLE_SELECTION_SEVEN_OPTIONS -> {
                var question30 = new MultipleSelectionQuestion();
                CustomBeanUtils.copyProperties(question, question30);
                question30.setOptions(options);
                question30.setAnswer((MultipleOptionAnswer) toAnswer(firstAnswerPO));
                question = question30;
            }
            // 40 计算问题
            case CALCULATION_NUMBER, CALCULATION_EXPRESSION -> {
                var question40 = new CalculationQuestion();
                CustomBeanUtils.copyProperties(question, question40);
                question40.setAnswer(toAnswer(firstAnswerPO));
                question = question40;
            }
            // 50 填空问题
            case COMPLETION_NUMBER, COMPLETION_SENTENCE, COMPLETION_RANGE, COMPLETION_DATETIME, COMPLETION_UNIT, COMPLETION_NUMBER_SERIES, COMPLETION_OPERATOR, COMPLETION_TEXT, COMPLETION_LATEX, COMPLETION_HYBRID -> {
                var question50 = new CompletionQuestion();
                CustomBeanUtils.copyProperties(question, question50);
                question50.setAnswers(answers);
                question = question50;
            }
            // 116 列式计算问题
            case COLUMN_CALCULATION_DIVISION, COLUMN_CALCULATION_PLUS, COLUMN_CALCULATION_MINUS, COLUMN_CALCULATION_TIMES -> {
                var question116 = new ColumnCalculationQuestion();
                CustomBeanUtils.copyProperties(question, question116);
                question116.setAnswer(toAnswer(firstAnswerPO));
                question = question116;
            }
            // 117 几何计算问题
            case GEOMETRY_CALCULATION_ANGLE_DEGREE, GEOMETRY_CALCULATION_EDGE_PERIMETER, GEOMETRY_CALCULATION_AREA, GEOMETRY_CALCULATION_VOLUME_CAPACITY -> {
                var question117 = new GeometryCalculationQuestion();
                CustomBeanUtils.copyProperties(question, question117);
                question117.setAnswer(toAnswer(firstAnswerPO));
                question = question117;
            }
            // 118 几何填空问题
            case GEOMETRY_COMPLETION_ANGLE_EDGE_RELATION, GEOMETRY_COMPLETION_POLYGON, GEOMETRY_COMPLETION_EDGE_ANGLE -> {
                var question118 = new GeometryCompletionQuestion();
                CustomBeanUtils.copyProperties(question, question118);
                question118.setAnswers(answers);
                question = question118;
            }
            // 119 文字应用
            case WORD -> {
                var question119 = new WordQuestion();
                CustomBeanUtils.copyProperties(question, question119);
                question119.setAnswers(answers);
                question = question119;
            }
            // 120 单位转换
            case UNIT_CONVERSION_MEASURE, UNIT_CONVERSION_MONEY -> {
                var question120 = new UnitConversionQuestion();
                CustomBeanUtils.copyProperties(question, question120);
                question120.setAnswers(answers);
                question = question120;
            }
            // 121 解方程
            case FORMULA_SOLVE_EQUATION, FORMULA_SOLVE_INEQUALITY -> {
                var question121 = new EquationInequalityQuestion();
                CustomBeanUtils.copyProperties(question, question121);
                question121.setAnswers(answers);
                question = question121;
            }
            // 122 推理证明
            case PROVE -> {
                var question122 = new ProveQuestion();
                CustomBeanUtils.copyProperties(question, question122);
                question122.setAnswers(answers);
                question = question122;
            }

            // 123 比与比例问题
            case RATION_PROPORTION_PROPORTION, RATION_PROPORTION_RATE, RATION_PROPORTION_RATIO -> {
                var question123 = new RatioProportionQuestion();
                CustomBeanUtils.copyProperties(question, question123);
                question123.setAnswer(toAnswer(firstAnswerPO));
                question = question123;
            }

            // 124 概率计算问题
            case PROBABILITY_CALCULATION -> {
                var question124 = new ProbabilityCalculationQuestion();
                CustomBeanUtils.copyProperties(question, question124);
                question124.setAnswer(toAnswer(firstAnswerPO));
                question = question124;
            }

            // 125 统计问题
            case STATISTICS_MEDIAN, STATISTICS_AVERAGE -> {
                var question125 = new StatisticsCalculationQuestion();
                CustomBeanUtils.copyProperties(question, question125);
                question125.setAnswer(toAnswer(firstAnswerPO));
                question = question125;
            }

            // 126 因数复数问题
            case FACTORS_MULTIPLES, COMMON_FACTOR_MULTIPLE -> {
                var question126 = new FactorsMultiplesQuestion();
                CustomBeanUtils.copyProperties(question, question126);
                question126.setAnswer(toAnswer(firstAnswerPO));
                question = question126;
            }
            default -> {
                logger.error("根据问题模式构建问题失败。");
                return null;
            }
        }

        question.setProblemId(question.getProblemId());
        question.setProblemType(problemType);
        question.setQuestionType(questionType);
        question.setQuestionTypeId(questionType.getTypeId());
        question.setQuestionHypertext(question.getQuestionHypertext());
        if (solutions.size() >= 1) {
            question.setSolutions(solutions);
            for (var solution : solutions) {
                if (solution.isPreferred())
                    question.setPreferredSolution(solution);
            }
        }
        question.setAction(question.getAction());
        loadScoringRule(question);
        return question;
    }

    private void loadScoringRule(@NotNull Question question) {
        long examId = problemAccessor.getExamIdByProblem(question.getProblemId());
        long problemTypeId = question.getProblemTypeId();
        long questionTypeId = question.getQuestionTypeId();
        var rule = examRepository.getScoringRule(examId, problemTypeId, questionTypeId);
        question.setScoringRule(rule);
    }

    public Option toOption(@NotNull QuestionOptionPO questionOption) {
        return ProblemConverter.Instance.toOption(questionOption);
    }

    public Solution toSolution(@NotNull QuestionSolutionPO questionSolution) {
        return ProblemConverter.Instance.toSolution(questionSolution);
    }

    public Answer toAnswer(@NotNull QuestionAnswerPO questionAnswer) {
        Answer answer;
        int answerTypeId = questionAnswer.getAnswerTypeId();
        if (answerTypeId <= 0) {
            logger.warn("无效的答案类型。答案类型编号: {}。", answerTypeId);
        }
        AnswerTypes answerType = AnswerTypes.valueOf(answerTypeId);
        switch (answerType) {
            case BOOLEAN -> answer = AnswerConverter.toBooleanAnswer(questionAnswer);
            case OPTION -> answer = AnswerConverter.toOptionAnswer(questionAnswer);
            case INTEGER -> answer = AnswerConverter.toIntegerAnswer(questionAnswer);
            case DECIMAL -> answer = AnswerConverter.toDecimalAnswer(questionAnswer);
            case FRACTION -> answer = AnswerConverter.toFractionAnswer(questionAnswer);
            case PERCENT -> answer = AnswerConverter.toPercentAnswer(questionAnswer);
            case RADICAL_NUMBER -> answer = AnswerConverter.toRadicalNumberAnswer(questionAnswer);
            case LATEX -> answer = AnswerConverter.toLatexAnswer(questionAnswer);
            case TEXT, GEOMETRY_ANGLE_EDGE_RELATION -> answer = AnswerConverter.toTextAnswer(questionAnswer);
            case INTEGER_RANGE -> answer = AnswerConverter.toIntegerRangeAnswer(questionAnswer);
            case DECIMAL_RANGE -> answer = AnswerConverter.toDecimalRangeAnswer(questionAnswer);
            case SCIENCE_NOTATION -> answer = AnswerConverter.toScienceNotationAnswer(questionAnswer);
            case MULTIPLE_OPTION -> answer = AnswerConverter.toMultipleOptionAnswer(questionAnswer);
            case QUOTIENT_REMINDER -> answer = AnswerConverter.toQuotientReminderAnswer(questionAnswer);
            case LOOP_DECIMAL_NUMBER -> answer = AnswerConverter.toLoopDecimalAnswer(questionAnswer);
            case PLUS_MINUS_EXPRESSION, TIMES_DIVISION_EXPRESSION, ARITHMETIC_EXPRESSION ->
                    answer = AnswerConverter.toExpressionAnswer(questionAnswer);
            case PLUS_MINUS_EQUATION, TIMES_DIVISION_EQUATION, ARITHMETIC_EQUATION ->
                    answer = AnswerConverter.toEquationAnswer(questionAnswer);
            case PLUS_MINUS_INEQUALITY, TIMES_DIVISION_INEQUALITY, ARITHMETIC_INEQUALITY ->
                    answer = AnswerConverter.toInequalityAnswer(questionAnswer);
            case DATE -> answer = AnswerConverter.toDateAnswer(questionAnswer);
            case TIME -> answer = AnswerConverter.toTimeAnswer(questionAnswer);
            case DATE_TIME -> answer = AnswerConverter.toDateTimeAnswer(questionAnswer);
            case RATIO -> answer = AnswerConverter.toRatioAnswer(questionAnswer);
            case PROPORTION -> answer = AnswerConverter.toProportionAnswer(questionAnswer);
            case RATE -> answer = AnswerConverter.toRateAnswer(questionAnswer);
            case COMPARE_OPERATOR ->
                    answer = AnswerConverter.toOperatorAnswer(questionAnswer, AnswerTypes.COMPARE_OPERATOR);
            case ARITHMETIC_OPERATOR ->
                    answer = AnswerConverter.toOperatorAnswer(questionAnswer, AnswerTypes.ARITHMETIC_OPERATOR);
            case MEASURE_UNIT_AREA, MEASURE_UNIT_LENGTH, MEASURE_UNIT_VOLUME, MEASURE_UNIT_CAPACITY, MEASURE_UNIT_WEIGHT ->
                    answer = AnswerConverter.toMeasureUnitAnswer(questionAnswer, AnswerTypes.MEASURE_UNIT_WEIGHT);
            case GEOMETRY_ANGLE_DEGREE -> answer = AnswerConverter.toAngleDegreeAnswer(questionAnswer);
            case GEOMETRY_VERTEX_DENOTE -> answer = AnswerConverter.toVertexDenoteAnswer(questionAnswer);
            case GEOMETRY_ANGLE_DENOTE -> answer = AnswerConverter.toAngleDenoteAnswer(questionAnswer);
            case GEOMETRY_EDGE_DENOTE -> answer = AnswerConverter.toEdgeDenoteAnswer(questionAnswer);
            case GEOMETRY_TRIANGLE_DENOTE -> answer = AnswerConverter.toTriangleDenoteAnswer(questionAnswer);
            case GEOMETRY_QUADRILATERAL_DENOTE -> answer = AnswerConverter.toQuadrilateralDenoteAnswer(questionAnswer);
            case GEOMETRY_PENTAGON_DENOTE -> answer = AnswerConverter.toPentagonDenoteAnswer(questionAnswer);
            case GEOMETRY_POINT_DENOTE -> answer = AnswerConverter.toPointDenoteAnswer(questionAnswer);
            case GEOMETRY_XY_POINT_DENOTE -> answer = AnswerConverter.toXYPointDenoteAnswer(questionAnswer);
            case GEOMETRY_XYZ_POINT_DENOTE -> answer = AnswerConverter.toXYZPointDenoteAnswer(questionAnswer);
            case INTEGER_SERIES -> answer = AnswerConverter.toIntegerSeriesAnswer(questionAnswer);
            case INTEGER_SERIES_SORTED, INTEGER_SERIES_DESC, INTEGER_SERIES_ASC ->
                    answer = AnswerConverter.toSortedIntegerSeriesAnswer(questionAnswer);
            case DECIMAL_SERIES -> answer = AnswerConverter.toDecimalSeriesAnswer(questionAnswer);
            case DECIMAL_SERIES_ASC, DECIMAL_SERIES_DESC ->
                    answer = AnswerConverter.toSortedDecimalSeriesAnswer(questionAnswer);
            case PROBABILITY -> answer = AnswerConverter.toProbabilityAnswer(questionAnswer);
            case EQUATION_SOLUTION -> answer = AnswerConverter.toEquationSolutionAnswer(questionAnswer);
            case INEQUALITY_SOLUTION -> answer = AnswerConverter.toInequalitySolutionAnswer(questionAnswer);
            default -> {
                logger.error("未发现匹配的答案类型校验方法。 {} / {}", answerType.getValue(), answerType.getName());
                return null;
            }
        }
        if (Objects.nonNull(answer)) {
            answer.setProblemId(questionAnswer.getProblemId());
            answer.setAnswerOptionId(questionAnswer.getAnswerOptionId());
            answer.setAction(questionAnswer.getAction());
            answer.setAnswerHypertext(questionAnswer.getAnswerHypertext());
        }
        return answer;
    }
    // endregion

    public Problem getProblem(long problemId) {
        //var problemPO = problemAccessor.getProblemPO(problemId);
        var problemView = problemAccessor.getProblemView(problemId);
        if (Objects.isNull(problemView)) return null;
        var problem = toProblem(problemView);
        //CustomBeanUtils.copyProperties(problemView, problem);

        return problem;
    }

    public Collection<Problem> getProblemsByIds(Collection<Long> problemIds) {
        var problems = new ArrayList<Problem>();
        for (var problemId : problemIds) {
            var problem = getProblem(problemId);
            if (Objects.nonNull(problem)) {
                problems.add(problem);
            }
        }
        return problems;
    }

    /*public Problem createProblemByType(long problemTypeId) {
        var problemType = problemTypeRepository.getProblemType(problemTypeId);
        if (problemType == null) return null;
        var problemMode = problemType.getProblemMode();
        var commonQuestionMode = problemType.getCommonQuestionMode();
        if (problemMode == null || commonQuestionMode == null) return null;

        return switch (problemMode) {
            case HYBRID -> new HybridProblem();
            case COMPOSITE -> createCompositeProblem(commonQuestionMode);
            case SIMPLE -> createSimpleProblem(commonQuestionMode);
        };
    }*/
    // endregion


    // region simple problem
    private SimpleProblem buildSimpleProblem(@NotNull ProblemPO problemPO, @NotNull QuestionModes questionMode, @NotNull QuestionPO firstQuestion) {
        SimpleProblem simpleProblem;
        switch (questionMode) {
            // 10 判断问题
            case TRUE_FALSE -> {
                simpleProblem = new TrueFalseProblem();
                var question1 = (TrueFalseQuestion) toQuestion(firstQuestion);
                ((TrueFalseProblem) simpleProblem).setQuestion(question1);
            }
            // 20 单选问题
            case MULTIPLE_CHOICE_TWO_OPTIONS, MULTIPLE_CHOICE_THREE_OPTIONS, MULTIPLE_CHOICE_FOUR_OPTIONS, MULTIPLE_CHOICE_FIVE_OPTIONS -> {
                simpleProblem = new MultipleChoiceProblem();
                var question2 = (MultipleChoiceQuestion) toQuestion(firstQuestion);
                ((MultipleChoiceProblem) simpleProblem).setQuestion(question2);
            }
            // 30 多选问题
            case MULTIPLE_SELECTION_FOUR_OPTIONS, MULTIPLE_SELECTION_FIVE_OPTIONS, MULTIPLE_SELECTION_SIX_OPTIONS, MULTIPLE_SELECTION_SEVEN_OPTIONS -> {
                simpleProblem = new MultipleSelectionProblem();
                var question3 = (MultipleSelectionQuestion) toQuestion(firstQuestion);
                ((MultipleSelectionProblem) simpleProblem).setQuestion(question3);
            }
            // 40 计算问题
            case CALCULATION_NUMBER, CALCULATION_EXPRESSION -> {
                simpleProblem = new CalculationProblem();
                var question4 = (CalculationQuestion) toQuestion(firstQuestion);
                ((CalculationProblem) simpleProblem).setQuestion(question4);
            }
            // 50 填空问题
            case COMPLETION_NUMBER, COMPLETION_SENTENCE, COMPLETION_RANGE, COMPLETION_DATETIME, COMPLETION_UNIT, COMPLETION_NUMBER_SERIES, COMPLETION_OPERATOR, COMPLETION_TEXT, COMPLETION_LATEX, COMPLETION_HYBRID -> {
                simpleProblem = new CompletionProblem();
                var question5 = (CompletionQuestion) toQuestion(firstQuestion);
                ((CompletionProblem) simpleProblem).setQuestion(question5);
            }
            // 116 列式计算问题
            case COLUMN_CALCULATION_DIVISION, COLUMN_CALCULATION_PLUS, COLUMN_CALCULATION_MINUS, COLUMN_CALCULATION_TIMES -> {
                simpleProblem = new ColumnCalculationProblem();
                var question10 = (ColumnCalculationQuestion) toQuestion(firstQuestion);
                ((ColumnCalculationProblem) simpleProblem).setQuestion(question10);
            }
            // 117 几何计算问题
            case GEOMETRY_CALCULATION_ANGLE_DEGREE, GEOMETRY_CALCULATION_EDGE_PERIMETER, GEOMETRY_CALCULATION_AREA, GEOMETRY_CALCULATION_VOLUME_CAPACITY -> {
                simpleProblem = new GeometryCalculationProblem();
                var question9 = (GeometryCalculationQuestion) toQuestion(firstQuestion);
                ((GeometryCalculationProblem) simpleProblem).setQuestion(question9);
            }
            // 118 几何填空问题
            case GEOMETRY_COMPLETION_ANGLE_EDGE_RELATION, GEOMETRY_COMPLETION_POLYGON, GEOMETRY_COMPLETION_EDGE_ANGLE -> {
                simpleProblem = new GeometryCompletionProblem();
                var question18 = (GeometryCompletionQuestion) toQuestion(firstQuestion);
                ((GeometryCompletionProblem) simpleProblem).setQuestion(question18);
            }
            // 119 文字应用
            case WORD -> {
                simpleProblem = new WordProblem();
                var question19 = (WordQuestion) toQuestion(firstQuestion);
                ((WordProblem) simpleProblem).setQuestion(question19);
            }
            // 120 单位转换
            case UNIT_CONVERSION_MEASURE, UNIT_CONVERSION_MONEY -> {
                simpleProblem = new UnitConversionProblem();
                var question11 = (UnitConversionQuestion) toQuestion(firstQuestion);
                ((UnitConversionProblem) simpleProblem).setQuestion(question11);
            }
            // 121 解方程/解不等式
            case FORMULA_SOLVE_EQUATION, FORMULA_SOLVE_INEQUALITY -> {
                simpleProblem = new EquationInequalityProblem();
                var question121 = (EquationInequalityQuestion) toQuestion(firstQuestion);
                ((EquationInequalityProblem) simpleProblem).setQuestion(question121);
            }
            // 122 推理证明
            case PROVE -> {
                simpleProblem = new ProveProblem();
                var question22 = (ProveQuestion) toQuestion(firstQuestion);
                ((ProveProblem) simpleProblem).setQuestion(question22);
            }

            // 123 比与比例问题
            case RATION_PROPORTION_PROPORTION, RATION_PROPORTION_RATE, RATION_PROPORTION_RATIO -> {
                simpleProblem = new RatioProportionProblem();
                var question12 = (RatioProportionQuestion) toQuestion(firstQuestion);
                ((RatioProportionProblem) simpleProblem).setQuestion(question12);
            }

            // 124 概率计算问题
            case PROBABILITY_CALCULATION -> {
                simpleProblem = new ProbabilityProblem();
                var question8 = (ProbabilityCalculationQuestion) toQuestion(firstQuestion);
                ((ProbabilityProblem) simpleProblem).setQuestion(question8);
            }

            // 125 统计问题
            case STATISTICS_MEDIAN, STATISTICS_AVERAGE -> {
                simpleProblem = new StatisticsProblem();
                var question7 = (StatisticsCalculationQuestion) toQuestion(firstQuestion);
                ((StatisticsProblem) simpleProblem).setQuestion(question7);
            }

            // 126 因数复数问题
            case FACTORS_MULTIPLES, COMMON_FACTOR_MULTIPLE -> {
                simpleProblem = new FactorsMultiplesProblem();
                var question6 = (FactorsMultiplesQuestion) toQuestion(firstQuestion);
                ((FactorsMultiplesProblem) simpleProblem).setQuestion(question6);
            }
            case SHORT_ANSWER -> {
                simpleProblem = new ShortAnswerProblem();
                var question128 = (ShortAnswerQuestion) toQuestion(firstQuestion);
                ((ShortAnswerProblem) simpleProblem).setQuestion(question128);
            }
            default -> {
                logger.error("简单题转换失败： 未知的问题模式转换。");
                return null;
            }
        }

        CustomBeanUtils.copyProperties(problemPO, simpleProblem);
        return simpleProblem;
    }

    /*public SimpleProblem createSimpleProblem(CommonQuestionModes commonQuestionMode) {
        SimpleProblem simpleProblemBO;
        switch (commonQuestionMode) {
            // 10 判断问题
            case TRUE_FALSE -> simpleProblemBO = new TrueFalseProblem();

            // 20 单选问题
            case MULTIPLE_CHOICE -> simpleProblemBO = new MultipleChoiceProblem();

            // 30 多选问题
            case MULTIPLE_SELECTION -> simpleProblemBO = new MultipleSelectionProblem();

            // 40 计算问题
            case CALCULATION -> simpleProblemBO = new CalculationProblem();

            // 50 填空问题
            case COMPLETION -> simpleProblemBO = new CompletionProblem();

            // 116 列式计算问题
            case COLUMN_CALCULATION -> simpleProblemBO = new ColumnCalculationProblem();

            // 117 几何计算问题
            case GEOMETRY_CALCULATION -> simpleProblemBO = new GeometryCalculationProblem();

            // 118 几何填空问题
            case GEOMETRY_COMPLETION -> simpleProblemBO = new GeometryCompletionProblem();

            // 119 文字应用
            case WORD -> simpleProblemBO = new WordProblem();

            // 120 单位转换
            case UNIT_CONVERSION -> simpleProblemBO = new UnitConversionProblem();

            // 121 解方程
            case FORMULA_SOLVE -> simpleProblemBO = new EquationInequalityProblem();

            // 122 推理证明
            case PROVE -> simpleProblemBO = new ProveProblem();


            // 123 比与比例问题
            case RATIO_PROPORTION -> simpleProblemBO = new RatioProportionProblem();


            // 124 概率计算问题
            case PROBABILITY -> simpleProblemBO = new ProbabilityProblem();


            // 125 统计问题
            case STATISTICS -> simpleProblemBO = new StatisticsProblem();


            // 126 因数复数问题
            case FACTORS_MULTIPLES -> simpleProblemBO = new FactorsMultiplesProblem();

            // 128 因数复数问题
            case SHORT_ANSWER -> simpleProblemBO = new ShortAnswerProblem();
            default -> {
                return null;
            }
        }
        return simpleProblemBO;
    }*/


    // endregion

    // region composite problem
    /*public CompositeProblem createCompositeProblem(CommonQuestionModes commonQuestionModes) {
        CompositeProblem compositeProblemBO;
        switch (commonQuestionModes) {
            // 10 判断问题
            case TRUE_FALSE:
                compositeProblemBO = new CompositeTrueFalseProblem();
                break;
            // 20 单选问题
            case MULTIPLE_CHOICE:
                compositeProblemBO = new CompositeMultipleChoiceProblem();
                break;
            // 30 多选问题
            case MULTIPLE_SELECTION:
                compositeProblemBO = new CompositeMultipleSelectionProblem();
                break;
            // 40 计算问题
            case CALCULATION:
                compositeProblemBO = new CompositeCalculationProblem();
                break;
            // 50 填空问题
            case COMPLETION:
                compositeProblemBO = new CompositeCompletionProblem();
                break;
            // 116 列式计算问题
            case COLUMN_CALCULATION:
                compositeProblemBO = new CompositeColumnCalculationProblem();
                break;
            // 117 几何计算问题
            case GEOMETRY_CALCULATION:
                compositeProblemBO = new CompositeGeometryCalculationProblem();
                break;
            // 118 几何填空问题
            case GEOMETRY_COMPLETION:
                compositeProblemBO = new CompositeGeometryCompletionProblem();
                break;
            // 119 文字应用
            case WORD:
                compositeProblemBO = new CompositeWordProblem();
                break;
            // 120 单位转换
            case UNIT_CONVERSION:
                compositeProblemBO = new CompositeUnitConversionProblem();
                break;
            // 121 解方程
            case FORMULA_SOLVE:
                compositeProblemBO = new CompositeEquationInequalityProblem();
                break;
            // 122 推理证明
            case PROVE:
                compositeProblemBO = new CompositeProveProblem();
                break;

            // 123 比与比例问题
            case RATIO_PROPORTION:
                compositeProblemBO = new CompositeRatioProportionProblem();
                break;

            // 124 概率计算问题
            case PROBABILITY:
                compositeProblemBO = new CompositeProbabilityProblem();
                break;

            // 125 统计问题
            case STATISTICS:
                compositeProblemBO = new CompositeStatisticsProblem();
                break;

            // 126 因数复数问题
            case FACTORS_MULTIPLES:
                compositeProblemBO = new CompositeFactorsMultiplesProblem();
                break;
            // 128 解答
            case SHORT_ANSWER:
                compositeProblemBO = new CompositeShortAnswerProblem();
                break;
            default:
                return null;
        }
        return compositeProblemBO;
    }*/

    private CompositeProblem buildCompositeProblem(@NotNull ProblemPO problemPO, @NotNull QuestionModes questionMode) {
        CompositeProblem compositeProblem;
        var questionPOs = problemPO.getQuestions();
        var questions = CollectionUtils.toArrayList(questionPOs, this::toQuestion);

        switch (questionMode) {
            // 10 判断问题
            case TRUE_FALSE -> {
                compositeProblem = new CompositeTrueFalseProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<TrueFalseQuestion> questionList1 = CollectionHelper.convertToArrayList(questions);
                ((CompositeTrueFalseProblem) compositeProblem).setQuestions(questionList1);
            }
            // 20 单选问题
            case MULTIPLE_CHOICE_TWO_OPTIONS, MULTIPLE_CHOICE_THREE_OPTIONS, MULTIPLE_CHOICE_FOUR_OPTIONS, MULTIPLE_CHOICE_FIVE_OPTIONS -> {
                compositeProblem = new CompositeMultipleChoiceProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<MultipleChoiceQuestion> questionList2 = CollectionHelper.convertToArrayList(questions);
                ((CompositeMultipleChoiceProblem) compositeProblem).setQuestions(questionList2);
            }
            // 30 多选问题
            case MULTIPLE_SELECTION_FOUR_OPTIONS, MULTIPLE_SELECTION_FIVE_OPTIONS, MULTIPLE_SELECTION_SIX_OPTIONS, MULTIPLE_SELECTION_SEVEN_OPTIONS -> {
                compositeProblem = new CompositeMultipleSelectionProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<MultipleSelectionQuestion> questionList3 = CollectionHelper.convertToArrayList(questions);
                ((CompositeMultipleSelectionProblem) compositeProblem).setQuestions(questionList3);
            }
            // 40 计算问题
            case CALCULATION_NUMBER, CALCULATION_EXPRESSION -> {
                compositeProblem = new CompositeCalculationProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<CalculationQuestion> questionList4 = CollectionHelper.convertToArrayList(questions);
                ((CompositeCalculationProblem) compositeProblem).setQuestions(questionList4);
            }
            // 50 填空问题
            case COMPLETION_NUMBER, COMPLETION_SENTENCE, COMPLETION_RANGE, COMPLETION_DATETIME, COMPLETION_UNIT, COMPLETION_NUMBER_SERIES, COMPLETION_OPERATOR, COMPLETION_TEXT, COMPLETION_LATEX, COMPLETION_HYBRID -> {
                compositeProblem = new CompositeCompletionProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<CompletionQuestion> questionList5 = CollectionHelper.convertToArrayList(questions);
                ((CompositeCompletionProblem) compositeProblem).setQuestions(questionList5);
            }
            // 116 列式计算问题
            case COLUMN_CALCULATION_DIVISION, COLUMN_CALCULATION_PLUS, COLUMN_CALCULATION_MINUS, COLUMN_CALCULATION_TIMES -> {
                compositeProblem = new CompositeColumnCalculationProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<ColumnCalculationQuestion> questionList10 = CollectionHelper.convertToArrayList(questions);
                ((CompositeColumnCalculationProblem) compositeProblem).setQuestions(questionList10);
            }
            // 117 几何计算问题
            case GEOMETRY_CALCULATION_ANGLE_DEGREE, GEOMETRY_CALCULATION_EDGE_PERIMETER, GEOMETRY_CALCULATION_AREA, GEOMETRY_CALCULATION_VOLUME_CAPACITY -> {
                compositeProblem = new CompositeGeometryCalculationProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<GeometryCalculationQuestion> questionList9 = CollectionHelper.convertToArrayList(questions);
                ((CompositeGeometryCalculationProblem) compositeProblem).setQuestions(questionList9);
            }
            // 118 几何填空问题
            case GEOMETRY_COMPLETION_ANGLE_EDGE_RELATION, GEOMETRY_COMPLETION_POLYGON, GEOMETRY_COMPLETION_EDGE_ANGLE -> {
                compositeProblem = new CompositeGeometryCompletionProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<GeometryCompletionQuestion> questionList18 = CollectionHelper.convertToArrayList(questions);
                ((CompositeGeometryCompletionProblem) compositeProblem).setQuestions(questionList18);
            }
            // 119 文字应用
            case WORD -> {
                compositeProblem = new CompositeWordProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<WordQuestion> questionList19 = CollectionHelper.convertToArrayList(questions);
                ((CompositeWordProblem) compositeProblem).setQuestions(questionList19);
            }
            // 120 单位转换
            case UNIT_CONVERSION_MEASURE, UNIT_CONVERSION_MONEY -> {
                compositeProblem = new CompositeUnitConversionProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<UnitConversionQuestion> questionList11 = CollectionHelper.convertToArrayList(questions);
                ((CompositeUnitConversionProblem) compositeProblem).setQuestions(questionList11);
            }
            // 121 解方程
            case FORMULA_SOLVE_EQUATION, FORMULA_SOLVE_INEQUALITY -> {
                compositeProblem = new CompositeEquationInequalityProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<EquationInequalityQuestion> questionList121 = CollectionHelper.convertToArrayList(questions);
                ((CompositeEquationInequalityProblem) compositeProblem).setQuestions(questionList121);
            }
            // 122 推理证明
            case PROVE -> {
                compositeProblem = new CompositeProveProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<ProveQuestion> questionList22 = CollectionHelper.convertToArrayList(questions);
                ((CompositeProveProblem) compositeProblem).setQuestions(questionList22);
            }
            // 123 比与比例问题
            case RATION_PROPORTION_PROPORTION, RATION_PROPORTION_RATE, RATION_PROPORTION_RATIO -> {
                compositeProblem = new CompositeRatioProportionProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<RatioProportionQuestion> questionList12 = CollectionHelper.convertToArrayList(questions);
                ((CompositeRatioProportionProblem) compositeProblem).setQuestions(questionList12);
            }
            // 124 概率计算问题
            case PROBABILITY_CALCULATION -> {
                compositeProblem = new CompositeProbabilityProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<ProbabilityCalculationQuestion> questionList8 = CollectionHelper.convertToArrayList(questions);
                ((CompositeProbabilityProblem) compositeProblem).setQuestions(questionList8);
            }
            // 125 统计问题
            case STATISTICS_MEDIAN, STATISTICS_AVERAGE -> {
                compositeProblem = new CompositeStatisticsProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<StatisticsCalculationQuestion> questionList7 = CollectionHelper.convertToArrayList(questions);
                ((CompositeStatisticsProblem) compositeProblem).setQuestions(questionList7);
            }

            // 126 因数复数问题
            case FACTORS_MULTIPLES, COMMON_FACTOR_MULTIPLE -> {
                compositeProblem = new CompositeFactorsMultiplesProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<FactorsMultiplesQuestion> questionList6 = CollectionHelper.convertToArrayList(questions);
                ((CompositeFactorsMultiplesProblem) compositeProblem).setQuestions(questionList6);
            }
            case SHORT_ANSWER -> {
                compositeProblem = new CompositeShortAnswerProblem();
                CustomBeanUtils.copyProperties(problemPO, compositeProblem);
                Collection<ShortAnswerQuestion> questionList128 = CollectionHelper.convertToArrayList(questions);
                ((CompositeShortAnswerProblem) compositeProblem).setQuestions(questionList128);
            }
            default -> {
                logger.error("组合题转换失败： 未知的问题模式转换。");
                return null;
            }
        }

        compositeProblem.setStem(toStem(problemPO.getStem()));
        return compositeProblem;
    }


    // endregion

    // region hybrid problem
    private HybridProblem buildHybridProblem(@NotNull ProblemPO problemPO) {
        HybridProblem hybridProblem = new HybridProblem();
        CustomBeanUtils.copyProperties(problemPO, hybridProblem);

        hybridProblem.setStem(toStem(problemPO.getStem()));
        var questions = CollectionHelper.convertToArrayList(problemPO.getQuestions(), this::toQuestion);
        hybridProblem.setQuestions(questions);

        return hybridProblem;
    }

    // endregion

    // region stem
    public Stem getStemByProblem(long problemId) {
        var stemPO = problemAccessor.getStemPOByProblem(problemId);
        if (Objects.isNull(stemPO)) return null;

        return ProblemConverter.Instance.toStem(stemPO);
    }

    // endregion

    // region question
    public Question getQuestion(long questionId) {
        var questionPO = problemAccessor.getQuestion(questionId);
        if (Objects.isNull(questionPO)) return null;

        return toQuestion(questionPO);
    }

    public Collection<Question> getQuestions(long problemId) {
        var questionPOs = problemAccessor.getQuestionPOs(problemId);
        return CollectionHelper.convertToArrayList(questionPOs, this::toQuestion);
    }


    /*public Question createQuestionByType(long problemTypeId, long questionTypeId, Collection<Solution> solutions, Collection<Answer> answers, Collection<Option> options) {
        var problemType = problemTypeRepository.getProblemType(problemTypeId);
        var questionType = questionTypeRepository.getQuestionType(questionTypeId);
        if (problemType == null) return null;
        var commonQuestionMode = problemType.getCommonQuestionMode();
        var correctAnswer = (Answer) answers.toArray()[0];
        var correctAnswers = answers;
        Question question = null;
        switch (commonQuestionMode) {
            case TRUE_FALSE:
                question = new TrueFalseQuestion();
                ((TrueFalseQuestion) question).setAnswer((BooleanAnswer) correctAnswer);
                break;
            case MULTIPLE_CHOICE:
                question = new MultipleChoiceQuestion();
                ((MultipleChoiceQuestion) question).setOptions(options);
                ((MultipleChoiceQuestion) question).setAnswer(null);
                break;
            case MULTIPLE_SELECTION:
                question = new MultipleSelectionQuestion();
                ((MultipleSelectionQuestion) question).setOptions(options);
                ((MultipleChoiceQuestion) question).setAnswer(null);
                break;
            case CALCULATION:
                question = new CalculationQuestion();
                ((CalculationQuestion) question).setAnswer(correctAnswer);
                break;
            case COMPLETION:
                question = new CompletionQuestion();
                ((CompletionQuestion) question).setAnswers(correctAnswers);
                break;
            case GEOMETRY_CALCULATION:
                question = new GeometryCalculationQuestion();
                ((CalculationQuestion) question).setAnswer(correctAnswer);
                break;
            case GEOMETRY_COMPLETION:
                question = new GeometryCompletionQuestion();
                ((GeometryCompletionQuestion) question).setAnswers(correctAnswers);
                break;
            case COLUMN_CALCULATION:
                question = new ColumnCalculationQuestion();
                ((ColumnCalculationQuestion) question).setAnswer(correctAnswer);
                break;
            case FORMULA_SOLVE:
                question = new EquationInequalityQuestion();
                ((EquationInequalityQuestion) question).setAnswers(correctAnswers);
                break;
            case WORD:
                question = new WordQuestion();
                ((WordQuestion) question).setAnswers(correctAnswers);
                break;
            case FACTORS_MULTIPLES:
                question = new FactorsMultiplesQuestion();
                ((FactorsMultiplesQuestion) question).setAnswer(correctAnswer);
                break;
            case PROBABILITY:
                question = new ProbabilityCalculationQuestion();
                ((ProbabilityCalculationQuestion) question).setAnswer(correctAnswer);
                break;
            case PROVE:
                question = new ProveQuestion();
                ((ProveQuestion) question).setAnswers(correctAnswers);
                break;
            case RATIO_PROPORTION:
                question = new RatioProportionQuestion();
                ((RatioProportionQuestion) question).setAnswer(correctAnswer);
                break;
            case STATISTICS:
                question = new StatisticsCalculationQuestion();
                ((StatisticsCalculationQuestion) question).setAnswer(correctAnswer);
                break;
            case UNIT_CONVERSION:
                question = new UnitConversionQuestion();
                ((UnitConversionQuestion) question).setAnswers(correctAnswers);
                break;
            case SHORT_ANSWER:
                question = new ShortAnswerQuestion();
                ((ShortAnswerQuestion) question).setAnswers(correctAnswers);
                break;
            default:
                logger.error("Failed to create simple problem.");
        }

        question.setProblemType(problemType);
        question.setQuestionType(questionType);
        question.getSolutions().addAll(solutions);
        question.setAction(Actions.CREATE);

        return question;
    }*/


    // endregion

    // region solution

    public Solution getSolution(long solutionId) {
        var solutionPO = problemAccessor.getSolutionPO(solutionId);
        if (Objects.isNull(solutionPO)) return null;

        return toSolution(solutionPO);
    }

    public Collection<Solution> getSolutions(long questionId) {
        var solutionPOs = problemAccessor.getSolutionPOs(questionId);
        return CollectionHelper.convertToArrayList(solutionPOs, this::toSolution);
    }
    // endregion

    // region answer


    public Answer getAnswer(@Min(0) long answerId) {
        var answerPO = problemAccessor.getAnswerPO(answerId);
        if (Objects.isNull(answerPO)) return null;
        return toAnswer(answerPO);
    }

    public Collection<Answer> getAnswers(long questionId) {
        var answerPOs = problemAccessor.getAnswerPOs(questionId);
        return CollectionHelper.convertToArrayList(answerPOs, this::toAnswer);
    }

    public Answer findAnswerByIndex(Collection<Answer> answers, int index) {
        for (var answer : answers) {
            if (answer.getAnswerIndex() == index)
                return answer;
        }
        return null;
    }


    // endregion

    // region option

    public Option getOption(@Min(0) long optionId) {
        var optionPO = problemAccessor.getOptionPO(optionId);
        if (Objects.isNull(optionPO)) return null;
        return toOption(optionPO);
    }

    public Collection<Option> getOptions(long questionId) {
        var optionPOs = problemAccessor.getOptionPOs(questionId);
        return CollectionHelper.convertToArrayList(optionPOs, this::toOption);
    }

    public int getOptionIndex(@NotEmpty Collection<Option> options, @Min(0) long optionId) {
        var optionalOption = options.stream().filter(o -> o.getOptionIndex() == optionId).findFirst();
        return optionalOption.map(Option::getOptionIndex).orElse(0);
    }

    public String getOptionPrefix(long optionId) {
        var optionPO = problemAccessor.getOptionPO(optionId);
        if (Objects.isNull(optionPO)) return "";

        var optionIndex = optionPO.getOptionIndex();
        return getOptionIndexPrefix(optionIndex);
    }

    public String getOptionIndexPrefix(@Min(0) int optionIndex) {
        return switch (optionIndex) {
            case 1 -> "A";
            case 2 -> "B";
            case 3 -> "C";
            case 4 -> "D";
            case 5 -> "E";
            case 6 -> "F";
            case 7 -> "G";
            case 8 -> "H";
            case 9 -> "I";
            default -> "";
        };
    }

    public String getOptionIdPrefix(@NotBlank Collection<Option> options, @Min(0) long optionId) {
        int index = getOptionIndex(options, optionId);
        return getOptionIndexPrefix(index);
    }

    public String getOptionIdsPrefix(@NotBlank Collection<Option> options, @NotBlank Collection<Long> optionIds) {
        var prefixes = new ArrayList<String>();
        for (var optionId : optionIds) {
            var prefix = getOptionIdPrefix(options, optionId);
            prefixes.add(prefix);
        }
        return StringUtils.join(prefixes, ",");
    }
    // endregion

    //region knowledge Points
    /*public ProblemKnowledgePoint toProblemSubjectPoint(ProblemPointView problemPoint) {
        var problemSubjectPoint = new ProblemKnowledgePoint();
        CustomBeanUtils.copyProperties(problemPoint, problemSubjectPoint);
        return problemSubjectPoint;
    }*/
    //endregion

    //region tags
    public Collection<TagName> getTagNamesByProblem(long problemId) {
        return tagGateway.getTagNamesByProblem(problemId);
        //return itemBuilder.getTagNamesByProblem(problemId);
    }
    //endregion

}
